﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace Sparklings.Rendering
{
    public class RenderContext : RenderTransform
    {
        public RenderContext(
            GraphicsDevice destination,
            ContentManager content,
            Vector2 renderTargetPixelSize,
            Vector2 dimensionsInTiles,
            Vector2 upperLeftCornerPositionInTiles = default(Vector2))
            : base(renderTargetPixelSize, dimensionsInTiles, upperLeftCornerPositionInTiles)
        {
            GraphicsDevice = destination;
            Content = content;
            effect = content.Load<Effect>("rendercontext");
            SetSamplersStates();
        }
        public ContentManager Content;
        public void Draw(Texture2D texture, Vector2 position)
        {
            Draw(texture, position, Color.White);
        }
        public void Draw(Texture2D texture, Vector2 position, Color c)
        {
            Draw(texture, position, c, 1.0f);
        }
        public void Draw(Texture2D texture, Vector2 position, Color c, float scale)
        {
            Draw(texture, position, c, scale, scale);
        }
        public void LoadGraphicsRelatedElements()
        {
            effect = Content.Load<Effect>("rendercontext");
        }
        private void SetSamplersStates()
        {
            SamplerState s = new SamplerState()
            {
                AddressU = TextureAddressMode.Clamp,
                AddressV = TextureAddressMode.Clamp,
                Filter = TextureFilter.Anisotropic
            };
            effect.GraphicsDevice.SamplerStates[0] = s;
            effect.GraphicsDevice.SamplerStates[1] = s;
            effect.GraphicsDevice.SamplerStates[2] = s;
        }
        public void Draw(Texture2D texture, Vector2 position, Color c, float scaleX, float scaleY)
        {
            if (texture.IsDisposed)
            {
                return;
            }
            VertexPositionTexture[] texPoints = GetRect(position, scaleX, scaleY);
            effect.CurrentTechnique = effect.Techniques["draw2d"];
            effect.Parameters["tex"].SetValue(texture);
            effect.Parameters["filterColor"].SetValue(c.ToVector4());
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, texPoints, 0, 2, VertexPositionTexture.VertexDeclaration);
            }
        }
        public GraphicsDevice GraphicsDevice { get; set; }
        private VertexPositionTexture[] GetRect(Vector2 center, float sizeX, float sizeY)
        {
            // Transforming coordinates.
            center = (center - UpperLeftCornerPositionInTiles) / DimensionsInTiles;
            center = -new Vector2(1.0f) + new Vector2(center.X, center.Y) * 2;
            center = new Vector2(center.X, -center.Y);
            sizeX *= 2 / DimensionsInTiles.X;
            sizeY *= 2 / DimensionsInTiles.Y;

            VertexPositionTexture[] ret = new VertexPositionTexture[6];
            VertexPositionTexture upl = new VertexPositionTexture
            {
                Position = new Vector3(center.X - 0.5f * sizeX, center.Y - 0.5f * sizeY, 0f),
                TextureCoordinate = new Vector2(0, 1f)
            };
            VertexPositionTexture upr = new VertexPositionTexture
            {
                Position = new Vector3(center.X + 0.5f * sizeX, center.Y - 0.5f * sizeY, 0f),
                TextureCoordinate = new Vector2(1f, 1f)
            };
            VertexPositionTexture downl = new VertexPositionTexture
            {
                Position = new Vector3(center.X - 0.5f * sizeX, center.Y + 0.5f * sizeY, 0f),
                TextureCoordinate = new Vector2(0, 0f)
            };
            VertexPositionTexture downr = new VertexPositionTexture
            {
                Position = new Vector3(center.X + 0.5f * sizeX, center.Y + 0.5f * sizeY, 0f),
                TextureCoordinate = new Vector2(1f, 0f)
            };

            ret[0] = downl;
            ret[1] = upr;
            ret[2] = upl;

            ret[3] = downl;
            ret[4] = downr;
            ret[5] = upr;
            return ret;
        }
        private Effect effect;
    }
}
